package com.joysuch.wwyt.bp.service.impl;

import cn.hutool.json.JSONUtil;
import cn.zlg.common.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joysuch.wwyt.api.dataaccess.bean.OrientationV3AlarmBean;
import com.joysuch.wwyt.bp.entity.AlarmMessage;
import com.joysuch.wwyt.bp.entity.bean.AlarmMeaasgeSearchBean;
import com.joysuch.wwyt.bp.entity.bean.AlarmMessageBean;
import com.joysuch.wwyt.bp.entity.vo.AlarmMessageVO;
import com.joysuch.wwyt.bp.enums.ApiAlarmSubTypeEnum;
import com.joysuch.wwyt.bp.enums.ApiAlarmTypeEnum;
import com.joysuch.wwyt.bp.mapper.AlarmMessageMapper;
import com.joysuch.wwyt.bp.service.AlarmMessageService;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.bean.SimpleListIntegerBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.enums.DeleteFlag;
import com.joysuch.wwyt.core.enums.ImageFlag;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseImageRepositoryService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.mh.service.MonitorPointDataWebSocketService;
import com.joysuch.wwyt.monitoringcenter.bean.AlarmMessageCountBean;
import com.joysuch.wwyt.monitoringcenter.bean.McAlarmMessageBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zr
 * @since 2021-12-09
 */
@Service
@Slf4j
public class AlarmMessageServiceImpl extends ServiceImpl<AlarmMessageMapper, AlarmMessage> implements AlarmMessageService {

    @Autowired
    private AlarmMessageMapper alarmMessageMapper;

    @Value("${wwyt.base.serverUrl}")
    private String serverUrl;

    @Autowired
    private BaseImageRepositoryService baseImageRepositoryService;

    @Autowired
    private MonitorPointDataWebSocketService monitorPointDataWebSocketService;

    @Autowired
    private BaseUserDao userDao;

    @Override
    public void saveOrUpdateAlarm(AlarmMessageBean alarmMessageBean) throws ApiBusinessException {
        log.info("接收到AI报警: " + alarmMessageBean.toString());
        AlarmMessage alarmMessage = new AlarmMessage();
        //对传入的数据的tenentId和orgCode做处理。
        AlarmMessage convert = convert(alarmMessageBean, alarmMessage);
        saveOrUpdate(convert);
        //大屏推送报警信息
        try {
            List<AlarmMessage> alarmMessageList = new ArrayList<>();
            alarmMessageList.add(convert);
            monitorPointDataWebSocketService.getAIAlarmMessage(alarmMessageList, "ADD", convert.getTenentId(), convert.getOrgCode());
        } catch (Exception e) {
            log.error("推送AI报警出错======");
            e.printStackTrace();
        }
    }

    /**
     * base64格式的数据转为图片并保存
     *
     * @param imgCode
     * @return
     * @throws ApiBusinessException
     */
    private Long saveImg(String imgCode, Long tenentId, String orgCode) throws ApiBusinessException {
        imgCode = imgCode.substring(imgCode.indexOf(",", 1) + 1, imgCode.length());
        Base64.Decoder decoder = Base64.getDecoder();
        try {
            // 解码
            byte[] b = decoder.decode(imgCode);
            Long imageId = null;
            try {
                imageId = baseImageRepositoryService.saveAIImage(b, tenentId, orgCode);
            } catch (Throwable throwable) {
                log.error("AI报警图片保存失败:", throwable);
            }
            return imageId;
        } catch (Exception e) {
            throw new ApiBusinessException(Status.IMAGE_UPLOAD_FAILED);
        }
    }


    @Override
    public ResultBean alarmMessagePage(AlarmMeaasgeSearchBean bean) {
        Page<AlarmMessage> alarmMessageIPage = getAlarmMessagePageData(bean);
        if (CollectionUtils.isNotEmpty(alarmMessageIPage.getRecords())) {
            List<AlarmMessageVO> alarmMessageVOS = convertDate(alarmMessageIPage.getRecords());
            return ResultBean.pageData(alarmMessageVOS, alarmMessageIPage.getTotal());
        }
        return ResultBean.pageData(new ArrayList<>(), alarmMessageIPage.getTotal());
    }

    @Override
    public Page<AlarmMessage> getAlarmMessagePageData(AlarmMeaasgeSearchBean bean) {
        Page<AlarmMessage> page = new Page<>(bean.getPage() + 1, bean.getSize());
        page.setSearchCount(false);
        Page<AlarmMessage> taskPage = alarmMessageMapper.getAlarmMessagePageData(page, bean);
        Long count = alarmMessageMapper.getAlarmMessageCount(bean);
        taskPage.setTotal(count);
        return taskPage;
    }

    @Override
    public List<AlarmMessage> findAllByAlarmTypeAndStatus(Integer alarmType, int status, Long tenentId, String orgCode) {
        return alarmMessageMapper.findAllByAlarmTypeAndStatus(alarmType, status, tenentId, orgCode);
    }

    @Override
    public List<AlarmMessageCountBean> findCameraAlarms(List<String> names, Long tenentId, String orgCode) {
        return alarmMessageMapper.findCameraAlarms(names,tenentId,orgCode);
    }


    /**
     * AI报警推送的信息转为本地数据库保存的信息
     *
     * @param alarmMessageBean
     * @param alarmMessage
     * @return
     * @throws ApiBusinessException
     */
    private AlarmMessage convert(AlarmMessageBean alarmMessageBean, AlarmMessage alarmMessage) throws ApiBusinessException {
        //TenentId和orgCode做兼容
        Long tenentId = alarmMessageBean.getTenentId();
        String orgCode = alarmMessageBean.getOrgCode();
        if (null == tenentId) {
            tenentId = 1L;
        }
        if (StringUtils.isBlank(orgCode) || "001".equals(orgCode)) {
            orgCode = "001-001";
        }
        alarmMessage.setUniqueId(alarmMessageBean.getUniqueId());
        alarmMessage.setAlarmType(alarmMessageBean.getAlarmType());
        alarmMessage.setAlarmTypeName(alarmMessageBean.getAlarmTypeName());
        //保存图片
        if (StringUtils.isNotBlank(alarmMessageBean.getAlarmPicData())) {
            Long id = saveImg(alarmMessageBean.getAlarmPicData(), tenentId, orgCode);
            alarmMessage.setAlarmPicId(id);
        }
        alarmMessage.setAlarmTime(new Date(alarmMessageBean.getAlarmTime() * 1000));
        alarmMessage.setAlarmInfo(Constant.LEFT_BRACKETS + alarmMessageBean.getCameraName() + Constant.RIGHT_BRACKETS + "发现异常报警,类型为:" + alarmMessageBean.getSubTypeName());
        alarmMessage.setSubType(alarmMessageBean.getSubType());
        alarmMessage.setSubTypeName(alarmMessageBean.getSubTypeName());
        alarmMessage.setCameraUrl(alarmMessageBean.getCameraUrl());
        alarmMessage.setCameraName(alarmMessageBean.getCameraName());
        //AI传过来时候0是已处理1是未处理,存入我们本地为了通用将状态反转
        if (null != alarmMessageBean.getStatus()) {
            alarmMessage.setStatus(1 == alarmMessageBean.getStatus() ? 0 : 1);
        } else {
            alarmMessage.setStatus(0);
        }
        alarmMessage.setTenentId(tenentId);
        alarmMessage.setOrgCode(orgCode);
        return alarmMessage;
    }

    /**
     * 数据库数据转换为前端格式
     *
     * @param alarmMessageList
     * @return
     */
    private List<AlarmMessageVO> convertDate(List<AlarmMessage> alarmMessageList) {
        List<AlarmMessageVO> result = new ArrayList<>();
        for (AlarmMessage alarmMessage : alarmMessageList) {
            AlarmMessageVO messageVO = new AlarmMessageVO();
            messageVO.setId(alarmMessage.getId());
            messageVO.setAlarmTypeName(alarmMessage.getAlarmTypeName());
            messageVO.setModule(ApiAlarmTypeEnum.getNameById(alarmMessage.getAlarmType()));
            messageVO.setSubTypeName(alarmMessage.getSubTypeName());
            messageVO.setAlarmInfo(alarmMessage.getAlarmInfo());
            //图片
            //messageVO.setPicUrl();
            messageVO.setCameraName(alarmMessage.getCameraName());
            messageVO.setStatus(1 == alarmMessage.getStatus() ? "已处理" : "未处理");
            messageVO.setAlarmTime(alarmMessage.getAlarmTime());
            BaseAttachmentBean baseAttachmentBean = new BaseAttachmentBean();
            if (null != alarmMessage.getAlarmPicId()) {
                baseAttachmentBean.setId(alarmMessage.getAlarmPicId());
                baseAttachmentBean.setDownloadUrl(serverUrl + "/image/view?id=" + alarmMessage.getAlarmPicId() + "&flag=" + ImageFlag.AIALARM.getCode());
                messageVO.setAlarmPic(baseAttachmentBean);
            }
            //处理人(目前只能我们这里处理报警)
            if (StringUtils.isNotBlank(alarmMessage.getHandlerBy())) {
                messageVO.setHandlerByName(userDao.getRealNameById(Long.valueOf(alarmMessage.getHandlerBy())));
            }
            messageVO.setAlarmInfo(alarmMessage.getAlarmInfo());
            messageVO.setHandleTime(alarmMessage.getHandleTime());
            messageVO.setHandleInfo(alarmMessage.getHandleInfo());
            messageVO.setReason(alarmMessage.getReason());
            messageVO.setReason(alarmMessage.getReason());
            messageVO.setSerialNumber(alarmMessage.getSerialNumber());
            messageVO.setProcessInstanceId(alarmMessage.getProcessInstanceId());
            result.add(messageVO);
        }
        return result;
    }

    @Override
    public Integer aiAlarmMessageCount(Long tenentId, String orgCode, List<Integer> typeList) {
        LambdaQueryWrapper<AlarmMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(AlarmMessage::getAlarmType, typeList)
                //未处理
                .eq(AlarmMessage::getStatus, 0)
                .eq(AlarmMessage::getDeleteFlag, DeleteFlag.EFFECTIVE.getCode())
                .eq(AlarmMessage::getTenentId, tenentId)
                .likeRight(AlarmMessage::getOrgCode, orgCode);
        return alarmMessageMapper.selectCount(wrapper);
    }

    @Override
    public AlarmMessage getMessageById(Long id) {
        LambdaQueryWrapper<AlarmMessage> wrapper = new LambdaQueryWrapper<>();
        //报警类型为AI报警
//       eq(AlarmMessage::getAlarmType, ApiAlarmTypeEnum.AI.getId())
        wrapper.eq(null != id, AlarmMessage::getId, id)
                //未处理
                .eq(AlarmMessage::getStatus, 0)
                .eq(AlarmMessage::getDeleteFlag, DeleteFlag.EFFECTIVE.getCode());
        return alarmMessageMapper.selectOne(wrapper);
    }

    @Override
    public void setAllMeaageHandled(String msg, String alarmReason, Long handleBy, Date now) {
        alarmMessageMapper.setAllMeaageHandled(msg, alarmReason, handleBy.toString(), now);
    }

    @Override
    public List<McAlarmMessageBean> queryAIAlarmMessage(Integer state, Integer alarmType) {
        Long currentTenantId = Context.getCurrentTenantId();
        String currentOrgCode = Context.getCurrentOrgCode();
        List<McAlarmMessageBean> result = new ArrayList<>();
        LambdaQueryWrapper<AlarmMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AlarmMessage::getDeleteFlag, DeleteFlag.EFFECTIVE.getCode())
                .eq(state != null, AlarmMessage::getStatus, state)
                .eq(alarmType != null, AlarmMessage::getAlarmType, alarmType)
                .eq(currentTenantId != null, AlarmMessage::getTenentId, currentTenantId)
                .likeRight(StringUtils.isNotBlank(currentOrgCode), AlarmMessage::getOrgCode, currentOrgCode)
                .orderByDesc(AlarmMessage::getAlarmTime)
                .last("limit 100");
        List<AlarmMessage> alarmMessageList = alarmMessageMapper.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(alarmMessageList)) {
            result = covertForBigScreen(alarmMessageList);
        }
        return result;
    }


    private List<McAlarmMessageBean> covertForBigScreen(List<AlarmMessage> alarmMessageList) {
        List<McAlarmMessageBean> result = new ArrayList<>();
        for (AlarmMessage alarmMessage : alarmMessageList) {
            McAlarmMessageBean bean = new McAlarmMessageBean();
            if (alarmMessage.getAlarmType().intValue() == 0) {
                bean.setClassify("视频AI报警");
            } else {
                bean.setClassify(ApiAlarmTypeEnum.getNameById(alarmMessage.getAlarmType()));
            }
            bean.setId(alarmMessage.getId());
            bean.setType(ApiAlarmTypeEnum.getNameById(alarmMessage.getAlarmType()));
            bean.setTitle(alarmMessage.getSubTypeName());
            bean.setContent(alarmMessage.getAlarmInfo());
            bean.setState(alarmMessage.getStatus());
            bean.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(alarmMessage.getAlarmTime()));
            bean.setCameraName(alarmMessage.getCameraName());
            bean.setSn(alarmMessage.getSn());
            BaseAttachmentBean baseAttachmentBean = new BaseAttachmentBean();
            if (null != alarmMessage.getAlarmPicId()) {
                baseAttachmentBean.setId(alarmMessage.getAlarmPicId());
                baseAttachmentBean.setDownloadUrl(serverUrl + "/image/view?id=" + alarmMessage.getAlarmPicId() + "&flag=" + ImageFlag.AIALARM.getCode());
                bean.setAlarmPic(baseAttachmentBean);
            }

            result.add(bean);
        }
        return result;
    }

    @Override
    public List<SimpleListIntegerBean> aIAlarmSubType(Integer alarmType) {
        List<SimpleListIntegerBean> beanList = alarmMessageMapper.aIAlarmSubType(alarmType);
        if (CollectionUtils.isNotEmpty(beanList)) {
            beanList.forEach(e -> e.setValue(e.getLabel()));
            return beanList;
        }
        return new ArrayList<>();
    }

    @Override
    public Integer findCameraAlarm(String cameraName, Long tenentId, String orgCode) {
        return alarmMessageMapper.findCameraAlarm(cameraName, tenentId, orgCode);
    }

    @Override
    public List<AlarmMessage> statsForCountInDay(LocalDateTime startTime, Long tenentId, String orgCode) {
        Date date = Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant());
        return alarmMessageMapper.statsForCountInDay(date, tenentId, orgCode);
    }

    @Override
    public void saveAlarm(String type, OrientationV3AlarmBean alarmBean) {
        AlarmMessage message = alarmMessageMapper.findByAlarmTypeNameAndSubTypeNameAndemployeeId(type, alarmBean);
        if (message == null) {
            message = new AlarmMessage();
        }
        convertAlarmData(type, message, alarmBean);
        saveOrUpdate(message);
        log.info("wwyt保存v3定位系统推送报警数据  --------->", JSONUtil.toJsonStr(message));
    }

    @Override
    public List<AlarmMessage> getAlarmTypesNumber(Long tenentId, String orgCode) {
        return alarmMessageMapper.getAlarmTypesNumber(tenentId, orgCode);
    }


    private void convertAlarmData(String type, AlarmMessage message, OrientationV3AlarmBean alarmBean) {
        message.setAlarmType(ApiAlarmTypeEnum.getIdByCode(type));
        message.setAlarmTypeName(type);
        message.setSubType(ApiAlarmSubTypeEnum.getIdByCode(alarmBean.getAlarmType()));
        message.setSubTypeName(ApiAlarmSubTypeEnum.getNameByCode(alarmBean.getAlarmType()));
        message.setEmployeeId(alarmBean.getUuid());
        message.setAlarmTime(new Date(alarmBean.getTime()));
        message.setUserCode(alarmBean.getCodeInfo());
        message.setAlarmInfo(alarmBean.getAlarmInfo());
        message.setAlarmLocation(alarmBean.getAlarmLocation());
        message.setRails(JSONUtil.toJsonPrettyStr(alarmBean.getRails()));
        message.setOrgCode(alarmBean.getOrgCode());
        message.setTenentId(alarmBean.getTenentId());
        message.setHandleInfo(alarmBean.getHandleInfo());
        message.setSn(alarmBean.getSn());
        message.setSerialNumber(alarmBean.getSerialNumber());
        message.setProcessInstanceId(alarmBean.getProcessInstanceId());
        if (alarmBean.getHandleTime() != null) {
            message.setHandleTime(new Date(alarmBean.getHandleTime()));
        }
        message.setStatus(alarmBean.getType().equals("alarm") ? 0 : 1);
    }
}
